﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using 历史记录.Helper;

namespace 历史记录.DataAccessLayer
{
    /// <summary>
    /// Sqlite 只支持SqlIte 已有类型
    /// </summary>
    public class SugarClient<T> : DisposableBase, IDAL<T>
      where T : Model, new()
    {
        /// <summary>
        /// 读写锁
        /// </summary>
        private ReaderWriterLockSlim RWLock { get; }

        private SqlSugarScope Db { get; }

        /// <summary>
        /// 构造函函数
        /// </summary>
        /// <param name="name">数据库路径</param>
        internal SugarClient(string source)
        {
            Db = new SqlSugarScope(new ConnectionConfig()
            {
                ConnectionString = $"DataSource={source}",
                DbType = DbType.Sqlite,
                InitKeyType = InitKeyType.Attribute,
                IsAutoCloseConnection = true,
                AopEvents = new AopEvents
                {
                    OnLogExecuting = (sql, p) =>
                    {
                        Console.WriteLine(sql);
                        Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
                    },
                    //OnLogExecuted = (sql, p) =>
                    //{
                    //    Console.WriteLine(sql);
                    //    Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
                    //},
                }
            });
            Db.DbMaintenance.CreateDatabase();
            RWLock = new ReaderWriterLockSlim();
        }

        /// <summary>
        /// 刪除记录
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public bool DeleteMany(string table, Expression<Func<T, bool>> predicate)
        {
            RWLock.EnterWriteLock();
            try
            {
                return Db.Deleteable(predicate).AS(table).ExecuteCommandHasChange();
            }
            finally
            {
                RWLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 删除表
        /// </summary>
        /// <param name="table">表名</param>
        /// <returns></returns>
        public bool DropTable(string table)
        {
            RWLock.EnterWriteLock();
            try
            {
                return Db.DbMaintenance.DropTable(table);
            }
            finally
            {
                RWLock.ExitWriteLock();
            }
        }

        /// <summary>
        /// 获取表名称列表
        /// </summary>
        /// <returns></returns>
        public List<string> GetTableList()
        {
            RWLock.EnterReadLock();
            try
            {
                return Db.DbMaintenance.GetTableInfoList().Select(a => a.Name).ToList();
            }
            finally
            {
                RWLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 创建新的表
        /// </summary>
        /// <typeparam name="T">数据模型</typeparam>
        /// <param name="table">表名</param>
        public void InitTables(string table)
        {
            RWLock.EnterWriteLock();
            try
            {
                var db = Db;
                db.MappingTables.Add(typeof(T).Name, table);
                db.CodeFirst.InitTables<T>();
            }
            finally
            {
                RWLock.ExitWriteLock();
            }
        }

        public bool Insertable(string table, List<T> insertObjs)
        {
            RWLock.EnterWriteLock();
            try
            {
                // Db.Fastest<T>().AS(table).BulkCopy(insertObjs);
                var db = Db.Insertable(insertObjs).AS(table);
                return db.ExecuteCommandIdentityIntoEntity();
            }
            finally
            {
                RWLock.ExitWriteLock();
            }
        }

        public DateTime Max(string table)
        {
            RWLock.EnterReadLock();
            try
            {
                return Db.Queryable<Model>().AS(table).Max(a => a.Id);
            }
            finally
            {
                RWLock.ExitReadLock();
            }
        }

        public DateTime Min(string table)
        {
            RWLock.EnterReadLock();
            try
            {
                return Db.Queryable<Model>().AS(table).Min(a => a.Id);
            }
            finally
            {
                RWLock.ExitReadLock();
            }
        }

        public IEnumerable<TResult> Queryable<TResult>(string table, Expression<Func<T, TResult>> Select, Expression<Func<T, bool>> Where = null) where TResult : new()
        {
            RWLock.EnterReadLock();
            try
            {
                var sq = Db.Queryable<T>().AS(table);
                if (Where != null) sq.Where(Where);
                return sq.Select(Select).ToList();
            }
            finally
            {
                RWLock.ExitReadLock();
            }
        }

        public IEnumerable<T> Queryable(string table, Expression<Func<T, bool>> Where = null)
        {
            RWLock.EnterReadLock();
            try
            {
                var sq = Db.Queryable<T>().AS(table);
                if (Where != null) sq.Where(Where);
                return sq.ToList();
            }
            finally
            {
                RWLock.ExitReadLock();
            }
        }

        protected override void OnDispose()
        {
            Db.Dispose();
        }
    }
}